package top.loonglove.newindexserver.entity;

import io.swagger.annotations.ApiModel;
import lombok.*;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import top.loonglove.common.base.entity.BaseEntity;
import top.loonglove.newindexserver.util.Status;

import javax.persistence.Column;
import javax.persistence.Table;
import javax.security.auth.Subject;
import java.util.Collection;

/**
 * @author : xgl
 * @version : 0.0.1
 * @date :2021/7/26 3:33
 * 用户认证类
 */
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Data
@ApiModel("用户注册类")
@Table(name = "account")
public class Account extends BaseEntity implements UserDetails, Authentication {
    @Column(name = "account_name",nullable = false)
    private String accountName;
    @Column(name = "account_password",nullable = false)
    private String accountPassWord;
    @Column(name = "register_ip",nullable = false)
    private String registerIp;
    @Column(name = "register_email",nullable = false)
    private String registerEmail;
    @Column(nullable = false)
    private Status status;
    private boolean authenticated = true;
    private Collection<? extends GrantedAuthority> authorities;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        return authorities;
    }

    /**
     * Returns the password used to authenticate the user.
     *
     * @return the password
     */
    @Override
    public String getPassword() {
        return getAccountPassWord();
    }

    /**
     * Returns the username used to authenticate the user. Cannot return
     * <code>null</code>.
     *
     * @return the username (never <code>null</code>)
     */
    @Override
    public String getUsername() {
        return getAccountName();
    }

    /**
     *指示用户的帐户是否已过期。无法验证过期帐户。
     *@return
     * <code>true<code>
     * 如果用户的帐户有效（即未过期），
     * <code>false<code> 如果不再有效（即过期）
     */
    @Override
    public boolean isAccountNonExpired() {
        return !status.equals(Status.INVALID);
    }

    /**
     * Indicates whether the user is locked or unlocked. A locked user cannot be
     * authenticated.
     *
     * @return <code>true</code> if the user is not locked, <code>false</code> otherwise
     */
    @Override
    public boolean isAccountNonLocked() {
        return !status.equals(Status.LOCK);
    }

    /**
     * 指示用户的凭据（密码）是否已过期。过期的凭据会阻止身份验证。
     *
     * @return <code>true</code> 如果用户的凭据有效（即未过期），
     * <code>false</code> if no longer valid (ie expired)
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return !status.equals(Status.PASSWORD_EXPIRED);
    }

    /**
     * Indicates whether the user is enabled or disabled. A disabled user cannot be
     * authenticated.
     *
     * @return <code>true</code> if the user is enabled, <code>false</code> otherwise
     */
    @Override
    public boolean isEnabled() {
        return !status.equals(Status.DISABLE);
    }

    @Override
    public Object getCredentials() {
        return accountPassWord;
    }

    @Override
    public Object getDetails() {
        return String.format("registerEmail:%s,registerIp:%s",registerEmail,registerIp );
    }

    @Override
    public Object getPrincipal() {
        return getAccountName();
    }

    @Override
    public boolean isAuthenticated() {
        return authenticated;
    }

    @Override
    public void setAuthenticated(boolean b) throws IllegalArgumentException {
        authenticated = b;
    }

    /**
     * Returns the name of this principal.
     *
     * @return the name of this principal.
     */
    @Override
    public String getName() {
        return getAccountName();
    }

    /**
     * Returns true if the specified subject is implied by this principal.
     *
     * <p>The default implementation of this method returns true if
     * {@code subject} is non-null and contains at least one principal that
     * is equal to this principal.
     *
     * <p>Subclasses may override this with a different implementation, if
     * necessary.
     *
     * @param subject the {@code Subject}
     * @return true if {@code subject} is non-null and is
     * implied by this principal, or false otherwise.
     * @since 1.8
     */
    @Override
    public boolean implies(Subject subject) {
        return Authentication.super.implies(subject);
    }

    public void setStatus(Status status) {
        this.setDel(status.equals(Status.INVALID));
        this.status = status;
    }

    @Override
    public void setDel(boolean del){
        this.status = Status.INVALID;
        super.setDel(del);
    }
}
